package assemblydecoder;

/**
 *
 * @author shai
 */
public class Command {
    
    private String _hexaCommand;
    private String _opcodeBinary;
    private String _raBinary;
    private String _rbBinary;
    private String _rcBinary;
    private String _numberBinary;
    private String _numberC2;
    private String _numberC1;
    private String _numberC3;
    
    public Command(String hexaCommand) throws Exception{
        this._hexaCommand = hexaCommand;
        
        if (_hexaCommand.length() != 8){
            throw new Exception("Command must be 8 digits length.");
        }
        
        String binaryCommand = "";
        for (int i = 0; i < 8; i++) {
            binaryCommand = binaryCommand + hexaCommandToBinaryCommand(String.valueOf(_hexaCommand.charAt(i)));
        }
;
        System.out.println("binaryCommand: "+binaryCommand);
        this._opcodeBinary = binaryCommand.substring(0, 5);
        this._raBinary = binaryCommand.substring(5, 10);
        this._rbBinary = binaryCommand.substring(10, 15);
        this._rcBinary = binaryCommand.substring(15, 20);
        this._numberBinary = binaryCommand.substring(20, 32);
        this._numberC2 = binaryCommand.substring(15, 32);
        this._numberC1 = binaryCommand.substring(10, 32);
        this._numberC3 = binaryCommand.substring(27, 32);
    }
    
    private String hexaCommandToBinaryCommand(String s) throws Exception{
        String ans ="";
        long tmp = 0;
        try{
            tmp = Long.valueOf(s, 16).longValue();
        } catch (Exception e) { throw new Exception("Non valid Hexa Command");}
        ans = Long.toBinaryString(tmp);
        if (s.charAt(0) == '0'){
            ans = "000" + ans;
        } else if (s.charAt(0) == '1'){
            ans = "000" + ans;
        } else if (s.charAt(0) == '2' || s.charAt(0) == '3'){
            ans = "00" + ans;
        } else if (s.charAt(0) >= '4' && s.charAt(0) <= '7'){
            ans = "0" + ans;
        }
        System.out.println("ans: "+ans);
        return ans;
    }
    public String getOpcodeName(){
        String ans = "";
        String[] commandNames = {"nop", "ld", "ldr", "st", "str", "la", "lar", "???", "opcode = 8", "opcode = 9", "???",
                                                 "???", "add", "addi", "sub", "neg", "???", "???", "???", "???", "and",
                                                 "andi", "or", "ori", "not", "brl", "shr", "shra", "shl", "shc", "???",
                                                 "stop"};
        int opcode = Integer.valueOf(_opcodeBinary, 2).intValue();
        if (opcode == 8){
            int c3 = (int)getNumberC3();
            switch (c3){
                case 1: ans = "br"; break;
                case 2: ans = "brzr"; break;
                case 3: ans = "brnz"; break;
                case 4: ans = "brpl"; break;
                case 5: ans = "brmi"; break;
            }
        } else if (opcode == 9){
            int c3 = (int)getNumberC3();
            switch (c3){
                case 1: ans = "brlnv"; break;
                case 2: ans = "brlzr"; break;
                case 3: ans = "brlnz"; break;
                case 4: ans = "brlpl"; break;
                case 5: ans = "brlmi"; break;
            }
        } else{
            ans = commandNames[Integer.valueOf(_opcodeBinary, 2).intValue()];
        }
        return ans;
    }
    public long getOpcode(){
        return Long.valueOf(_opcodeBinary, 2);
    }
    public long getRa(){
        return Long.valueOf(_raBinary, 2);
    }
    public long getRb(){
        return Long.valueOf(_rbBinary, 2);
    }
    public long getRc(){
        return Long.valueOf(_rcBinary, 2);
    }
    public long getNumber(){
        return Long.valueOf(_numberBinary, 2);
    }
    public long getNumberC2(){
        return Long.valueOf(_numberC2, 2);
    }
    public long getNumberC1(){
        return Long.valueOf(_numberC1, 2);
    }
    public long getNumberC3(){
        return Long.valueOf(_numberC3, 2);
    }
    
    public String getOpcodeBinary() {
        return _opcodeBinary;
    }

    public String getRaBinary() {
        return _raBinary;
    }

    public String getRbBinary() {
        return _rbBinary;
    }

    public String getRcBinary() {
        return _rcBinary;
    }

    public String getNumberBinary() {
        return _numberBinary;
    }

    public String getNumberC2Binary() {
        return _numberC2;
    }

    public String getNumberC1Binary() {
        return _numberC1;
    }

    public String getNumberC3Binary() {
        return _numberC3;
    }
}
